package com.sprite.utils;

import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.MissingResourceException;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sprite.utils.cache.UtilCache;

/**
 * @author Jack
 */
public final class UtilProperties {

    private static final Logger logger = LoggerFactory.getLogger(UtilProperties.class);

    private static final UtilCache<Properties> resourceCache = UtilCache.createUtilCache("properties.UtilPropertiesResourceCache");

    private static final UtilCache<Properties> urlCache = UtilCache.createUtilCache("properties.UtilPropertiesUrlCache");

    public static String getPropertyValue(String resource, String name, String defaultValue) {
        String value = getPropertyValue(resource, name);

        if (UtilString.isEmpty(value))
            return defaultValue;
        else
            return value;
    }

    public static double getPropertyNumber(String resource, String name, double defaultValue) {
        String str = getPropertyValue(resource, name);
        if (str == null) {
            return defaultValue;
        }

        try {
            return Double.parseDouble(str);
        } catch (NumberFormatException nfe) {
            return defaultValue;
        }
    }

    public static double getPropertyNumber(String resource, String name) {
        return getPropertyNumber(resource, name, 0.00000);
    }


    public static Boolean getPropertyAsBoolean(String resource, String name, boolean defaultValue) {
        String str = getPropertyValue(resource, name);
        if ("true".equalsIgnoreCase(str)) return Boolean.TRUE;
        else if ("false".equalsIgnoreCase(str)) return Boolean.FALSE;
        else return defaultValue;
    }


    public static BigInteger getPropertyAsBigInteger(String resource, String name, BigInteger defaultNumber) {
        String strValue = getPropertyValue(resource, name);
        BigInteger result = defaultNumber;
        try {
            result = new BigInteger(strValue);
        } catch (NumberFormatException nfe) {
            logger.warn("Couldnt convert String \"" + strValue + "\" to BigInteger; using defaultNumber " + defaultNumber.toString() + ".");
        }
        return result;
    }

    public static BigDecimal getPropertyAsBigDecimal(String resource, String name, BigDecimal defaultNumber) {
        String strValue = getPropertyValue(resource, name);
        BigDecimal result = defaultNumber;
        try {
            result = new BigDecimal(strValue);
        } catch (NumberFormatException nfe) {
            logger.warn("Couldnt convert String \"" + strValue + "\" to BigDecimal; using defaultNumber " + defaultNumber.toString() + ".");
        }
        return result;
    }

    public static String getPropertyValue(String resource, String name) {
        if (resource == null || resource.length() <= 0) return "";
        if (name == null || name.length() <= 0) return "";

        Properties properties = getProperties(resource);
        if (properties == null) {
            return "";
        }

        String value = null;

        try {
            value = properties.getProperty(name);
        } catch (Exception e) {
            logger.warn("", e);
        }
        return value == null ? "" : value.trim();
    }

    public static Properties getProperties(String resource) {
        if (resource == null || resource.length() <= 0) {
            return null;
        }
        String cacheKey = resource;
        Properties properties = resourceCache.get(cacheKey);
        if (properties == null) {
            try {
                URL url = UtilURL.fromResource(resource);

                if (url == null)
                    return null;
                String fileName = url.getFile();
                File file = new File(fileName);
                if (file.isDirectory()) {
                    logger.warn(fileName + " is (also?) a directory! No properties assigned.");
                    return null;
                }
                properties = getProperties(url);
                resourceCache.put(cacheKey, properties);
            } catch (MissingResourceException e) {
                logger.warn("", e);
            }
        }
        if (properties == null) {
            logger.warn("[UtilProperties.getProperties] could not find resource: " + resource);
            return null;
        }
        return properties;
    }

    public static Properties getProperties(URL url) {
        if (url == null) {
            return null;
        }
        Properties properties = urlCache.get(url.toString());
        if (properties == null) {
            try {
                properties = new Properties();
                properties.load(url.openStream());
                urlCache.put(url.toString(), properties);
            } catch (Exception e) {
                logger.warn("", e);
            }
        }
        if (properties == null) {
            logger.warn("[UtilProperties.getProperties] could not find resource: ");
            return null;
        }
        return properties;
    }


    private UtilProperties() {
    }
}
